#include "WXTPlatformDevice.h"
#include <unistd.h>
#include "Encrypt/SM4Encrypt.h"
#include <Command/WXTProtocol/WXTIssueKeyCmd.h>
#include <Command/WXTProtocol/WXTMessageAuthenticationCmd.h>


WXTPlatformDevice::WXTPlatformDevice(QObject *parent) :
    BaseInterface<WXTPlatformDevice>(parent)
{

    m_pInstance = this;
    wxtProtocol = new WXTProtocol(this);

    this->registerProtocol(wxtProtocol);
    qDebug()<<" WXTPlatformDevice Start";

    timer = new QTimer(this);
    timer->setInterval(30000);//10 miao 1shi 60fen 3600miao
    timer->setSingleShot(true);
    connect(timer, SIGNAL(timeout()), this, SLOT(timeoutSlot()));
   // timer->start();

    registerCmdHandler(WXTLoginLewinCmd::FunctionCode,WXTLoginLewinCmd::staticMetaObject, &WXTPlatformDevice::loginLewinCmdHandle);
    registerCmdTimeOUTHandler(WXTAuthenticationCmd::FunctionCode,&WXTPlatformDevice::authenticationCmdHanle);
    registerCmdHandler(WXTIssueKeyCmd::FunctionCode,WXTIssueKeyCmd::staticMetaObject,&WXTPlatformDevice::issueKeyCmdHanle);
    registerCmdHandler(WXTMessageAuthenticationCmd::FunctionCode,WXTMessageAuthenticationCmd::staticMetaObject, &WXTPlatformDevice::messageAuthenticationCmdHanle);
}
void WXTPlatformDevice::onReceiveSM4InitComplete()
{
    qDebug()<<"WXTPlatformDevice::onReceiveSM4InitComplete()";
    sendLoginPlatform();

}


void WXTPlatformDevice::loginLewinCmdHandle(PortStruct source, QSharedPointer<BaseCmd> sharedCmd)
{
    Q_UNUSED(source);
   WXTLoginLewinCmd *loginLewinCmd = qobject_cast<WXTLoginLewinCmd*>(sharedCmd.data());
   qDebug()<<"in WXTPlatformDevice::loginLewinCmdHandle";
   m_CloudToken=loginLewinCmd->getToken();
   qDebug()<<"token is "<<loginLewinCmd->getToken();

   sendP7MessageAuth();
   //sendIssueKeyAuthentication(loginLewinCmd->getToken());


   /*  quint16 responseCode = responseCmd->responseCode();
    if(responseCode != 0)
    {
        reconnectTcpSrever();
    }*/
}
void WXTPlatformDevice::messageAuthenticationCmdHanle(PortStruct source, QSharedPointer<BaseCmd> sharedCmd)
{
    qDebug()<<"messageAuthenticationCmdHanle::";
    sendIssueKeyAuthentication(getCloudToken());
}



void WXTPlatformDevice::issueKeyCmdHanle(PortStruct source, QSharedPointer<BaseCmd> sharedCmd)
{
    Q_UNUSED(source);
    WXTIssueKeyCmd *wxtIssueKeyCmd = qobject_cast<WXTIssueKeyCmd*>(sharedCmd.data());
    qDebug()<<"WXTPlatformDevice::issueKeyCmdHanle";
    qDebug()<<"key is "<<wxtIssueKeyCmd->getKey();
    SM4Encrypt* sm4= SM4Encrypt::getInstance();
    sm4->ImportSessionKey(wxtIssueKeyCmd->getKey());

    //rzheng
    // sendP7MessageAuth();
}
void WXTPlatformDevice::authenticationCmdHanle(PortStruct source, QSharedPointer<BaseCmd> sharedCmd)
{
    Q_UNUSED(source);
    qDebug()<<"WXTPlatformDevice::authenticationCmdHanle";
}




QByteArray WXTPlatformDevice::getCloudToken()
{
    return m_CloudToken;
}



void WXTPlatformDevice::timeoutSlot()
{
    qDebug()<<"WXTPlatformDevice:: timeoutSlot sendP7MessageAuth 2fen";
//  issue_device();

    sendP7MessageAuth();
   // sendLoginPlatform();
}



QByteArray WXTPlatformDevice::build_messageAuth_Request_Data(){
    QVariantMap jsonData;
    QJson::Serializer serializer;
    SM4Encrypt* sm4=SM4Encrypt::getInstance();
    //jsonData.insert("type","authorization");
  //  jsonData.insert("appid","zjb_test");
    jsonData.insert("path","api/v1/se/key/issue");
    QVariantMap key_issive_jsonData;
    key_issive_jsonData.insert("seId",sm4->getSeId());
    key_issive_jsonData.insert("encCert",sm4->getSignedCert());
    QStringList qlist;
    qlist << "MFMK_SUB";
    key_issive_jsonData.insert("keyAlias",QVariant::fromValue(qlist));
    key_issive_jsonData.insert("wrapMethod","2");
    QByteArray data_req_issue= serializer.serialize(key_issive_jsonData, NULL);
    jsonData.insert("body",data_req_issue);

    QByteArray body = serializer.serialize(jsonData, NULL);
    qDebug()<<"build_messageAuth_Request_Data   "<<body;
    return body;
}
QByteArray WXTPlatformDevice::build_P7MessageAuth_Request_Data(){
    QVariantMap jsonData;
    QJson::Serializer serializer;
    SM4Encrypt* sm4=SM4Encrypt::getInstance();
    //jsonData.insert("type","authorization");
  //  jsonData.insert("appid","zjb_test");
    jsonData.insert("path","messageAuth");
    QVariantMap key_issive_jsonData;
    key_issive_jsonData.insert("type","authorization");
    key_issive_jsonData.insert("appid","zjb_test");

    key_issive_jsonData.insert("clientip",getLocalIpAddresses());
    key_issive_jsonData.insert("signdata",sm4->getGenP7AuthData());
    key_issive_jsonData.insert("plain",sm4->getGenP7AuthDataRaw());
    QByteArray data_req_issue= serializer.serialize(key_issive_jsonData, NULL);
    jsonData.insert("body",data_req_issue);

    QByteArray body = serializer.serialize(jsonData, NULL);
    qDebug()<<"build_messageAuth_Request_Data   "<<body;
    return body;
}
QString WXTPlatformDevice::getLocalIpAddresses()
{
    QString localHostName = QHostInfo::localHostName();
    QHostInfo hostInfo = QHostInfo::fromName(localHostName);

    foreach (QHostAddress address, hostInfo.addresses()) {
        if (address.protocol() == QAbstractSocket::IPv4Protocol) {
            qDebug() << "Local IP Address:" << address.toString();
            return address.toString();
        }
    }
    return "127.0.0.1";
}


void WXTPlatformDevice::sendP7MessageAuth()
{
    SM4Encrypt* sm4=SM4Encrypt::getInstance();

    QByteArray reqbody=build_P7MessageAuth_Request_Data();
    qDebug()<<" WXTPlatformDevice::sendP7MessageAuth ";
    QByteArray body=reqbody;
    WXTMessageAuthenticationCmd *wXTMessageAuthenticationCmd = new WXTMessageAuthenticationCmd();

    struct SeData sedata;
    sedata.nRet=0;
    sedata.hEnv=hEnv;


    // body = build_messageAuth_Request_Data();
     wXTMessageAuthenticationCmd->setBody(body);
     wXTMessageAuthenticationCmd->setSeData(sedata);
     QMap<QByteArray, QByteArray> map=getHead(getCloudToken());
     wXTMessageAuthenticationCmd->setHead(map);


    QSharedPointer<BaseCmd> sharedWXTAuthenticationCmd(wXTMessageAuthenticationCmd);


    PortStruct target;

    foreach (const BasePort *port , m_portList)
    {
         if((port->portParam().type() == "HttpClient"
             && port->portParam().name() == "WXTHttpClient"))
         {
             target = port->portParam();
             qDebug()<<"WXTPlatformDevice::sendP7MessageAuth";
         }
    }

    this->sendCmd(target,sharedWXTAuthenticationCmd);


}
   void WXTPlatformDevice::sendLoginPlatform()
   {

         QByteArray body;
         WXTLoginLewinCmd *wxtLoginLewinCmd = new WXTLoginLewinCmd();
         struct SeData sedata;
         sedata.nRet=0;
         sedata.hEnv=hEnv;
          body = "{\"username\":\"admin\",\"password\":\"88888888\"}";
          wxtLoginLewinCmd->setBody(body);
          wxtLoginLewinCmd->setSeData(sedata);


          QSharedPointer<BaseCmd> sharedWXTLoginLewinCmd(wxtLoginLewinCmd);


          PortStruct target;

          foreach (const BasePort *port , m_portList)
          {
               if((port->portParam().type() == "HttpClient"
                   && port->portParam().name() == "WXTHttpClient"))
               {
                   target = port->portParam();
                   qDebug()<<"WXTPlatformDevice::sendLoginPlatform";
               }
          }

          this->sendCmd(target,sharedWXTLoginLewinCmd);

   }


   QMap<QByteArray, QByteArray> WXTPlatformDevice::getHead(QByteArray token)
   {
       QMap<QByteArray,QByteArray> map;
       map.insert("SEAuth","Basic d3h0X3Rlc3Q6V1hUdGVzdDEx");
       map.insert("Authorization","Bearer "+token);
       return map;
   }
   void WXTPlatformDevice::sendIssueKeyAuthentication(QByteArray token)
   {
       QByteArray body;
       WXTAuthenticationCmd *wxtAuthenticationCmd = new WXTAuthenticationCmd();

       struct SeData sedata;
       sedata.nRet=0;
        sedata.hEnv=hEnv;
        body = build_messageAuth_Request_Data();
        wxtAuthenticationCmd->setBody(body);
        wxtAuthenticationCmd->setSeData(sedata);
        QMap<QByteArray, QByteArray> map=getHead(token);
        wxtAuthenticationCmd->setHttpHead(map);

       QSharedPointer<BaseCmd> sharedWXTAuthenticationCmd(wxtAuthenticationCmd);

//request.setRawHeader("Authorization","Basic d3h0X3Rlc3Q6V1hUdGVzdDEx");
       PortStruct target;

       foreach (const BasePort *port , m_portList)
       {
            if((port->portParam().type() == "HttpClient" && port->portParam().name() == "WXTHttpClient"))
            {
                target = port->portParam();
                qDebug()<<"WXTPlatformDevice::sendAuthentication";
            }
       }

       this->sendCmd(target,sharedWXTAuthenticationCmd);
   }


   int WXTPlatformDevice::messageEncrypt()
   {
            qDebug()<<"in WXTPlatformDevice::messageEncrypt";
   }






quint32 WXTPlatformDevice::issue_device(void)
{
/*
    unsigned char ucSignCert[8192] = {0};
    unsigned int nSignCertLen = sizeof(ucSignCert);
    unsigned char ucCipher[1024] = {0};
    unsigned int nCipherLen = sizeof(ucCipher);
    unsigned char ucData[] = "this is a test data for encrypt!";
    unsigned int nDataLen = sizeof(ucData);
    qDebug()<<"in WXTPlatformDevice::issue_device";
    char szSeId[256] = {0};
   //QByteArray szData = "<html>The plaintext message.</html>";
    char szData[] = "<html>The plaintext message.</html>";
   //  unsigned char ucSignedData[8192] = {0};
    unsigned int nSignedDataLen = sizeof(m_SignedData);
   // char ucEncode[128]={0};
  //  qint32 nRet;
   // void* hEnv;
    char* szDeviceId;
    System *system = System::getInstance();

    QString uuid = system->ReadUuid();
    uuid  ="356516100008031";

    QByteArray ba = uuid.toLatin1();
    szDeviceId = ba.data();

    nRet = SE_Initialize(&hEnv,0,szDeviceId,NULL,NULL,NULL);
    if(SAR_OK != nRet){
        qDebug()<<"SE_Initialize fail ret "<<nRet;
    }
    else
    {
            //get se id
        memset(&m_stSeAppInfo,0,sizeof(SEAPPINFO));
        nRet = SE_GetSEInfo(hEnv,&m_stSeAppInfo);
        if(SAR_OK != nRet)
        {
         qDebug()<<"SE_GetSEInfo fail ret "<<nRet;
           // printf("SE_Initialize fail ret : 0x%08X \n", nRet);
            return 0;// goto fail;
        }
        for(int i=0; i<16; i++)
        {
            sprintf(szSeId+2*i, "%02x", m_stSeAppInfo.SEID[i]);
        }
         qDebug()<<"SE_GetSEID success. SEID :"<<szSeId;
        //export certificate
        nRet = SE_ExportCertificate(hEnv, 1, ucSignCert, &nSignCertLen);
        //nRet = SE_ExportCertificate(hEnv, 0, ucSignCert, &nSignCertLen);
        if(SAR_OK != nRet)
        {
            qDebug()<<"SE_ExportCertificate fail ret :"<< nRet;
            return 0;// goto fail
        }

        qDebug()<<"SE_ExportCertificate success. p10 :  \n"<< ucSignCert;
        char tt[1024];
        memcpy(tt,ucSignCert,nSignCertLen);
        QByteArray temucSignCert(tt);

        {
             qDebug()<<"p10 16::\n";
            QString str;
            for(int i=0;i<nSignCertLen;i++)
            {
                str+=QString("%1").arg((unsigned char)temucSignCert.at(i),2,16,QLatin1Char('0'))+' ';
            }
            qDebug()<<str;  //打印十六进制数据

        }

      //  printf("SE_GetSEID success. SEID : %s\n", szSeId);

        nRet = SE_SymmOp(hEnv, 0, NULL, 0, ucData, nDataLen, ucCipher, &nCipherLen);
        if(SAR_OK != nRet)
        {
            qDebug()<<"SE_SymmOp (encrypt) fail ret : "<<nRet;

            return 0; //goto fail;
        }
        qDebug()<<"SE_SymmOp (encrypt) success.nDataLen:%d；nCipherLen:%d\n"<<nDataLen<<nCipherLen;
        char tmpCipher[1024];
        memcpy(tmpCipher,ucCipher,1024);
        QByteArray qba(tmpCipher);
       // strcpy(m_enCode,qba.toBase64().data());
        qDebug()<<"ucCipher base64 data-- "<<qba.toBase64();


        //
//        for(int i=0; i<16; i++)
//        sprintf(m_szSeId+2*i,"%02x",m_stSeAppInfo.SEID[i]);
//        qDebug()<<"SE_GetSEID sucess,SEID :  "<<QString(m_szSeId);
//        memset(m_SignedData,0,sizeof(m_SignedData));
//        nRet = SE_GenP7AuthData(hEnv, (unsigned char*)szData, strlen(szData),
//                                m_SignedData, &nSignedDataLen);
//        if(SAR_OK != nRet)
//        {
//             qDebug()<<"SE_GenP7AuthData fail. ret : 0x%08X \n"<< nRet;
//            return 0;// goto fail;
//        }
//        qDebug()<<"SE_GenP7AuthData OK";

//        memset(m_enCode,0,sizeof(m_enCode));
//        QByteArray qba(szData);
//        strcpy(m_enCode,qba.toBase64().data());
//        qDebug()<<"base64 data-- "<<qba.toBase64();

//       // build_messageAuth_Request_Data(m_enCode,(char*)m_SignedData);
//        sendAuthentication();


    }
*/
    return 1;
}
